package com.aura.springbook.service.impl;

import com.aura.springbook.common.constant.BookConstants;
import com.aura.springbook.common.enums.BorrowStatusEnum;
import com.aura.springbook.common.util.BorrowUtil;
import com.aura.springbook.mapper.BookMapper;
import com.aura.springbook.mapper.BorrowRecordMapper;
import com.aura.springbook.model.Book;
import com.aura.springbook.model.BorrowRecord;
import com.aura.springbook.service.BorrowRecordService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 借阅记录服务实现类
 * <p>
 * 继承MyBatis-Plus的ServiceImpl，实现BorrowRecordService接口
 * 提供借阅记录相关的业务逻辑实现
 * <p>
 * 主要功能：
 * 1. 借阅图书（创建借阅记录，减少图书库存）
 * 2. 归还图书（更新借阅记录，增加图书库存）
 * 3. 查询借阅记录
 */
@Service
public class BorrowRecordServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements BorrowRecordService {

    private static final Logger logger = LoggerFactory.getLogger(BorrowRecordServiceImpl.class);

    @Autowired
    private BorrowRecordMapper borrowRecordMapper;

    @Autowired
    private BookMapper bookMapper;

    /**
     * 借阅图书
     * <p>
     * 创建借阅记录并减少图书库存
     * 使用@Transactional注解保证数据一致性
     *
     * @param userId 用户ID
     * @param bookId 图书ID
     * @return 借阅记录ID
     * @throws RuntimeException 当图书库存不足时抛出异常
     */
    @Override
    @Transactional
    public Long borrowBook(Long userId, Long bookId) {
        logger.debug("开始借阅图书, 用户ID: {}, 图书ID: {}", userId, bookId);
        
        // 检查图书库存
        Book book = bookMapper.selectById(bookId);
        if (book == null || book.getStock() <= 0) {
            logger.warn("借阅图书失败, 图书库存不足, 图书ID: {}", bookId);
            throw new RuntimeException(BookConstants.ERROR_BOOK_STOCK_EMPTY);
        }

        // 创建借阅记录
        BorrowRecord borrowRecord = new BorrowRecord();
        borrowRecord.setUserId(userId);
        borrowRecord.setBookId(bookId);
        borrowRecord.setBorrowTime(LocalDateTime.now()); // 设置借阅时间
        borrowRecord.setStatusEnum(BorrowStatusEnum.NOT_RETURNED); // 0表示未归还

        // 保存借阅记录
        borrowRecordMapper.insert(borrowRecord);

        // 更新图书库存
        book.setStock(book.getStock() - 1);
        bookMapper.updateById(book);

        logger.info("借阅图书成功, 借阅记录ID: {}, 用户ID: {}, 图书ID: {}", borrowRecord.getId(), userId, bookId);
        return borrowRecord.getId();
    }

    /**
     * 归还图书
     * <p>
     * 更新借阅记录状态并增加图书库存
     * 使用@Transactional注解保证数据一致性
     *
     * @param recordId 借阅记录ID
     * @return 是否归还成功
     * @throws RuntimeException 当借阅记录不存在或已归还时抛出异常
     */
    @Override
    @Transactional
    public boolean returnBook(Long recordId) {
        logger.debug("开始归还图书, 借阅记录ID: {}", recordId);
        
        // 查询借阅记录
        BorrowRecord borrowRecord = borrowRecordMapper.selectById(recordId);
        if (borrowRecord == null || BorrowUtil.isReturned(borrowRecord)) {
            logger.warn("归还图书失败, 借阅记录不存在或已归还, 借阅记录ID: {}", recordId);
            throw new RuntimeException(BookConstants.ERROR_BORROW_RECORD_NOT_FOUND);
        }

        // 更新借阅记录状态
        borrowRecord.setStatusEnum(BorrowStatusEnum.RETURNED); // 1表示已归还
        borrowRecord.setReturnTime(LocalDateTime.now()); // 设置归还时间
        borrowRecordMapper.updateById(borrowRecord);

        // 更新图书库存
        int result = borrowRecordMapper.increaseBookStock(borrowRecord.getBookId());
        boolean success = result > 0;
        
        if (success) {
            logger.info("归还图书成功, 借阅记录ID: {}", recordId);
        } else {
            logger.warn("归还图书失败, 更新图书库存失败, 借阅记录ID: {}", recordId);
        }
        return success;
    }

    /**
     * 分页查询用户的借阅记录
     * <p>
     * 按用户ID查询借阅记录，按借阅时间倒序排列
     *
     * @param userId  用户ID
     * @param current 当前页
     * @param size    每页大小
     * @return 借阅记录分页数据
     */
    @Override
    public IPage<BorrowRecord> getBorrowRecordsByUser(Long userId, int current, int size) {
        logger.debug("开始分页查询用户借阅记录, 用户ID: {}, 当前页: {}, 每页大小: {}", userId, current, size);
        
        Page<BorrowRecord> page = new Page<>(current, size);
        QueryWrapper<BorrowRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.orderByDesc("borrow_time");
        IPage<BorrowRecord> result = borrowRecordMapper.selectPage(page, queryWrapper);
        
        logger.debug("分页查询用户借阅记录完成, 用户ID: {}, 总记录数: {}", userId, result.getTotal());
        return result;
    }

    /**
     * 根据ID获取借阅记录详情
     * <p>
     * 直接调用Mapper根据ID查询借阅记录
     *
     * @param id 借阅记录ID
     * @return 借阅记录详情
     */
    @Override
    public BorrowRecord getBorrowRecordDetail(Long id) {
        logger.debug("开始获取借阅记录详情, 借阅记录ID: {}", id);
        
        BorrowRecord record = borrowRecordMapper.selectById(id);
        if (record != null) {
            logger.debug("获取借阅记录详情成功, 借阅记录ID: {}", id);
        } else {
            logger.warn("获取借阅记录详情失败, 借阅记录ID: {} 不存在", id);
        }
        return record;
    }
}